/* eslint-disable */
import { defaultErrorHandler } from '../error-handler';
import { getToken, getTokenWithAuth } from '../tokens';
import ajax, { ExtraFetchParams, WrappedFetchParams } from './ajax';
import { validataResponse } from './response-validate';
import { ApiServiceName } from './service-name';
import { whitelist, WhitelistConf } from './whitelist';
// import { useLoginInforStore } from '@/store/login';
// 结果类型处理，如果是白名单里的下载，返回值改为 File，否则返回值为 result.result

type WhitelistKey = keyof typeof whitelist;

type IsDownloadKey<K> = K extends WhitelistKey ? ('download' extends keyof typeof whitelist[K] ? true : false) : false;

type GetResult<T> = 'data' extends keyof T ? T['data'] : void;

type GetApiResult<K, T> = T extends (...args: infer U) => Promise<infer V>
  ? IsDownloadKey<K> extends true
    ? (...args: U) => Promise<File>
    : (...args: U) => Promise<GetResult<V>>
  : never;

type GetApiResultList<T> = {
  [K in keyof T]: GetApiResult<K, T[K]>;
};

/**
 * 对 api 进行包装
 * @param apiRaw
 * @returns
 */
export const wrapApi = <T>(serviceName: ApiServiceName, apiRaw: T): GetApiResultList<T> => {
  const apiWrapped = {} as GetApiResultList<T>;

  for (const operationId of Object.keys(apiRaw)) {
    const apiFnRaw = apiRaw[operationId];

    apiWrapped[operationId] = async (...args: unknown[]) => {
      const opt = (args[apiFnRaw.length - 1] ?? {}) as ExtraFetchParams;

      // 白名单：下载文件：标记一下，在封装的ajax中处理
      const whitelistConf = whitelist[operationId] as WhitelistConf | undefined;
      if (whitelistConf?.download) {
        opt.extra = {
          download: true,
          ...opt.extra,
        };
      }

      // 添加token
      if (getTokenWithAuth()) {
        opt.headers = {
          Authorization: getTokenWithAuth(),
          ...opt.headers,
        };
      }

      args[apiFnRaw.length - 1] = opt;

      let result: {
        statusCode?: number;
        errMsg?: string;
        data?: T;
      };

      try {
        result = await apiFnRaw.call(apiRaw, ...args);
      } catch (err) {
        // 去登录
        if (err.response?.statusCode === 401) {
          err.message = '未登录';
        }
        throw err;
      }
      // 白名单：下载文件：跳过返回值验证
      if (whitelistConf) {
        return result;
      }

      if (result.statusCode === undefined) {
        throw new Error(result.errMsg ?? '未知错误');
      }

      if (result.statusCode !== 0) {
        // throw new Error(result.errMsg ?? '未知错误');
        defaultErrorHandler(result.errMsg);
        return;
      }

      // validataResponse(serviceName, operationId, result);

      return result.data as T;
    };
  }

  return apiWrapped;
};

/**
 * 对非 swagger api 进行包装
 * @param serviceName
 * @param apiRaw
 * @returns
 */
const rawApiFetch = async <T>(
  param: WrappedFetchParams & {
    withoutToken?: boolean;
    allowEmptyResult?: boolean;
  }
): Promise<T> => {
  // 添加token
  if (!param.withoutToken) {
    param.headers = {
      token: getTokenWithAuth(),
      ...param.headers,
    };
  }

  let result: {
    statusCode?: number;
    errMsg?: string;
    data?: T;
  };
  try {
    result = await ajax.ajax(param);
  } catch (err) {
    // 去登录
    if (err.response?.status === 401) {
      err.message = '未登录';
    }
    throw err;
  }

  if (!String(result.statusCode).startsWith('2')) {
    throw new Error(result.errMsg ?? '');
  }

  if (!param.allowEmptyResult && !result.data) {
    throw new Error(result.errMsg ?? '');
  }

  return result.data as T;
};
export const RawApi = {
  fetch: rawApiFetch,
};
